﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters;
using System.Net.Sockets; 

namespace TypedROBIN.Imaging
{
    [Serializable]
    public class RemotingRegister
    {
        /// <summary> 
        /// Create the .NET Remoting server using code. 
        /// </summary> 
        public static void CreateRemotingServerByCode(int hostPort = 8181)
        {
            // Create and register a channel (TCP channel in this example) that  
            // is used to transport messages across the remoting boundary. 

            // Set the properties of the channel. 
            IDictionary props = new Hashtable();
            props["port"] = hostPort.ToString();   // Port of the TCP channel 
            props["typeFilterLevel"] = TypeFilterLevel.Full;

            // Create the formatters of the messages for delivery. 
            BinaryClientFormatterSinkProvider clientProvider = null;
            BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
            serverProvider.TypeFilterLevel = TypeFilterLevel.Full;

            // Create a TCP channel. 
            TcpChannel tcpChannel = new TcpChannel(props, clientProvider, serverProvider);

            // Register the TCP channel. 
            ChannelServices.RegisterChannel(tcpChannel, true);

            // Register the remotable types on the service project as server-activated  
            // types (aka well-known types) or client-activated types. 

            //// Register RemotingShared.SingleCallObject as a  
            //// SingleCall Server-Activated type. 
            //RemotingConfiguration.RegisterWellKnownServiceType(
            //    Type.GetType("TypedROBIN.Imaging.PageSnapr, IECaptService"), // Server-activated type 
            //    "IECaptService",                     // objectUri 
            //    WellKnownObjectMode.SingleCall           // SingleCall instancing mode 
            //    );

            // Register RemotingShared.SingletonObject as a  
            // Singleton Server-Activated type. 
            RemotingConfiguration.RegisterWellKnownServiceType(
                Type.GetType("TypedROBIN.Imaging.IECaptEngine, IECaptService"), // Server-activated type 
                "IECaptService",                     // objectUri 
                WellKnownObjectMode.Singleton           // Singleton instancing mode 
                );

            //// Register RemotingShared.ClientActivatedObject as a  
            //// Client-Activated type. 
            //RemotingConfiguration.ApplicationName = "IECaptService";
            //RemotingConfiguration.RegisterActivatedServiceType(Type.GetType("TypedROBIN.Imaging.PageSnapr, IECaptService"));
            //Console.WriteLine("Server is ready");
        }

        /// <summary> 
        /// Create the .NET Remoting server using a configuration file. 
        /// </summary> 
        public static void CreateRemotingServerByConfig()
        {
            // Read the configuration file and configure the remoting  
            // infrastructure for the server project. 

            // The format for .NET Remoting configuration file: 
            // http://msdn.microsoft.com/en-us/library/ms973907.aspx 
            RemotingConfiguration.Configure("IECaptService.exe.config", true);
        }

        /// <summary> 
        /// Access the .NET Remoting server using code. 
        /// </summary> 
        public static IIECaptEngine GetRemotingProxyByCode(
            string remoteHost = "localhost", 
            int hostPort = 8181, 
            int clientPort = 8182)
        {
            IIECaptEngine pageSnaprFactory = null;

            // Create and register a channel (TCP channel in this example) that  
            // is used to transport messages across the remoting boundary. 

            // Set the properties of the channel. 
            IDictionary props = new Hashtable();
            props["name"] = "tcp client";
            props["typeFilterLevel"] = TypeFilterLevel.Full;
            props["port"] = clientPort.ToString();

            // Set the formatters of the messages for delivery. 
            BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
            BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
            serverProvider.TypeFilterLevel = TypeFilterLevel.Full;

            // Create a TCP channel. 
            TcpChannel tcpChannel = new TcpChannel(props, clientProvider, serverProvider);

            // Register the TCP channel. 
            ChannelServices.RegisterChannel(tcpChannel, true);

            try
            {
                // 
                // Create a remotable object. 
                // 

                // Create a SingleCall server-activated proxy. 
                //SingleCallObject remoteObj = (SingleCallObject)Activator.GetObject(
                //    typeof(SingleCallObject),
                //    "tcp://localhost:6100/SingleCallService");
                //Console.WriteLine("A SingleCall server-activated proxy is created");

                // [-or-] Create a Singleton server-activated proxy 
                pageSnaprFactory = (IIECaptEngine)Activator.GetObject(
                    typeof(IIECaptEngine),
                    "tcp://" + remoteHost + ":" + hostPort.ToString() + "/IECaptService");
                Console.WriteLine("A singleton server-activated proxy is created"); 

                // [-or-] Create a client-activated object 
                //RemotingConfiguration.RegisterActivatedClientType(
                //    typeof(IPageSnapr),
                //    "tcp://" + remoteHost + ":" + hostPort.ToString() + "/IECaptService");
                //ClientActivatedObject remoteObj = new ClientActivatedObject();
                //Console.WriteLine("A client-activated object is created"); 

            }
            catch (SocketException ex)
            {
                Console.WriteLine(ex.Message);
            }
            return pageSnaprFactory;
        }
    
    }
}
